package com.jming.jike.util;

import com.alibaba.fastjson.JSON;
import com.jming.jike.common.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author jinming.zhang
 */
@Slf4j
@Component
public class RedisUtil {

    @Value("${spring.redis.lockTime:15}")
    private int lockTime;

    @Resource
    public RedisTemplate<String, String> redisTemplate;


    public <T> List<T> getArray(String key, Class<T> clazz) {
        try {
            String value = redisTemplate.opsForValue().get(key);
            if (!StringUtils.hasText(value)) {
                return null;
            }
            return JSON.parseArray(value, clazz);
        } catch (Exception e) {
            log.error("RedisUtil getArray 读取数组缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
        }

        return null;
    }

    public Boolean setIfAbsentWillThrow(String key, String value) {
        try {
            return redisTemplate.opsForValue().setIfAbsent(key, value, lockTime, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("RedisUtil setIfAbsent 读写对象缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
            throw new BusinessException("服务器异常");
        }
    }

    /**
     * 设置指定过期时间的值
     *
     * @param key
     * @param value
     * @param lockTime
     * @return Boolean
     * @Author jinming.zhang
     * @Date 2022/5/26
     */
    public Boolean setIfAbsentWillThrow(String key, String value, int lockTime) {
        try {
            return redisTemplate.opsForValue().setIfAbsent(key, value, lockTime, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("RedisUtil setIfAbsent 读写对象缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
            throw new BusinessException("服务器异常");
        }
    }

    public String getKeyWillThrow(String key) {
        try {
            return redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            log.error("RedisUtil getObject 读取对象缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
            throw new BusinessException("服务器异常");
        }
    }

    public <T> T getObject(String key, Class<T> clazz) {
        try {
            String value = redisTemplate.opsForValue().get(key);
            if (!StringUtils.hasText(value)) {
                return null;
            }
            return JSON.parseObject(value, clazz);
        } catch (Exception e) {
            log.error("RedisUtil getObject 读取对象缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
        }

        return null;
    }

    public void setStringIfAbsent(String key, String value) {
        try {
            redisTemplate.opsForValue().setIfAbsent(key, value, lockTime, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("RedisUtil setObject 设置对象缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
        }
    }

    public Long increment(String key, long value) {
        try {
            return redisTemplate.opsForValue().increment(key, value);
        } catch (Exception e) {
            log.error("RedisUtil increment increment 入参 {}", key);
            log.error(e.getMessage(), e);
            throw new BusinessException("increment ERROR");
        }
    }

    public void setObjectIfAbsent(String key, Object object) {
        try {
            redisTemplate.opsForValue().setIfAbsent(key, JSON.toJSONString(object), lockTime, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("RedisUtil setObject 设置对象缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
        }
    }

    public void setObject(String key, Object object) {
        try {
            redisTemplate.opsForValue().set(key, JSON.toJSONString(object));
        } catch (Exception e) {
            log.error("RedisUtil setObject 设置对象缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
        }
    }


    public void setObjectWillThrow(String key, Object object) {
        try {
            redisTemplate.opsForValue().set(key, JSON.toJSONString(object), lockTime, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("RedisUtil setObject 设置对象缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
            throw new BusinessException("服务器异常");
        }
    }

    public <T> Boolean queryDelete(String key, Class<T> clazz) {
        Boolean result = Boolean.FALSE;

        try {

            result = (this.getObject(key, clazz) == null) || Boolean.TRUE.equals(redisTemplate.delete(key));
        } catch (Exception e) {
            log.error("RedisUtil delete 删除缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
        }

        return result;
    }

    public Boolean delete(String key) {
        Boolean result = Boolean.FALSE;

        try {
            result = redisTemplate.delete(key);
        } catch (Exception e) {
            log.error("RedisUtil delete 删除缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
        }

        return result;
    }

    public Boolean getDelete(String key) {
        Boolean result = Boolean.FALSE;

        try {

            result = this.getKeyWillThrow(key) == null || Boolean.TRUE.equals(redisTemplate.delete(key));
        } catch (Exception e) {
            log.error("RedisUtil delete 删除缓存失败 入参 {}", key);
            log.error(e.getMessage(), e);
        }

        return result;
    }


    public Long delete(List<String> keys) {
        Long result = 0L;

        try {
            result = redisTemplate.delete(keys);
        } catch (Exception e) {
            log.error("RedisUtil delete 删除缓存失败 入参 {}", keys);
            log.error(e.getMessage(), e);
        }

        return result;
    }

}
